<?php
/**
 * 帐号数据处理接口
 * Created by PhpStorm.
 * User: zhongbaitong
 * Date: 2020/5/21
 * Time: 19:12
 */

namespace app\controller;

use app\service\Cipher;
use app\service\Emailer;
use sys\Mysql;
use sys\Cache;

class Account extends Base
{

    /**
     * 登录处理
     * @url [post]:/account/login
     * @input account   string  账号
     * @input password  string  密码
     * @return false|string
     */
    public function login()
    {
        // 限制
        $login_error_num = $_COOKIE['login_error_num'] ?? 0;
        if ($login_error_num >= 5) {
            return $this->apiError(config("tips.login_baned"));
        }

        // 输入获取与过滤
        $input = $this->getInput("account,password");
        $account = $input["account"];
        $password = Cipher::encrypt($input["password"]);
        $user_id = $this->toCheckLoginInput($account, $password);
        if (!$user_id) {
            $login_error_num++;
            setcookie('login_error_num', $login_error_num, time() + 600);
            return $this->apiError(config("tips.login_err"));
        }

        //  session 保存登陆状态
        //  cookie  保存用户信息
        $this->toSetLoginInfo($user_id);
        $user_info = $this->toGetUserInfoById($user_id);
        return $this->apiSuccess(config("tips.login_ok"), compact("user_info"));
    }

    /**
     * 退出登陆
     * @url [get]:/account/logout
     * @return false|string
     */
    public function logout()
    {
        setcookie("user_info", null, time() - 999, "/");
        unset($_SESSION['isLogin']);
        return $this->apiSuccess();
    }

    /**
     * 发送邮箱验证码
     * @url [get]:/account/sendCodeToEmail
     * @input email  string  合法邮箱
     * @return false|string
     */
    public function sendCodeToEmail()
    {
        $input = $this->getInput("email");
        $email = $input["email"];
        if (!is_email($email)) {
            return $this->apiError(config("tips.email_format_err"));
        }
        // 获取 Redis 实例
        $cache = Cache::getInstance();
        // 已发送过验证码
        if ($cache->get($email)) {
            return $this->apiSuccess(config("tips.email_send_ok"));
        }

        // 获取 emailer 实例
        $emailer = Emailer::getInstance();
        $code = rand(100000, 999999);
        $content = "【ATONG APP】您的验证码是 <span style='color: #6bff57'>%s</span>，10 分钟内有效，请不要把验证码泄漏给其他人，如非本人操作请忽略";
        $rs = $emailer->send([
            "obj_email" => $email,
            "obj_username" => "尊敬的注册用户",
            "title" => "验证码信息",
            "content" => sprintf($content, $code)
        ]);
        if ($rs == "ok") {// 记录缓存
            $cache->set($email, $code, 600);
            return $this->apiSuccess(config("tips.email_send_ok"));
        }
        return $this->apiError($rs);
    }

    /**
     * 注册帐号｜ 修改密码
     * @url [post]:/account/register
     * @input account  string  帐号
     * @input code     string  验证码
     * @input password string  密码
     * @input re_password      确认密码
     * @return false|string
     */
    public function register()
    {
        $input = $this->getInput(["account", "code", "password", "re_password"]);
        $check_result = $this->toCheckRegisterInput($input);
        if (0 === $check_result["code"]) {
            return $this->apiError($check_result["msg"]);
        }

        // 帐号是否已存在
        $mysql = Mysql::getInstance();
        $sql = 'SELECT `id` FROM `fd_user` WHERE `email` = \'' . $input["account"] . '\'';
        $user = $mysql->getFind($sql);
        $password = Cipher::encrypt($input['password']);
        $client_ip = get_client_ip();
        if (isset($user["id"]) && $user["id"]) {
            // 已存在：修改密码
            $msg = config("tips.account_update_ok");
            $sql = <<<sql
UPDATE `fd_user`
SET password = '{$password}',
 last_login_ip = '{$client_ip}',
 update_time = NOW()
WHERE
	id = {$user["id"]};
sql;
        } else {
            // 不存在：新增帐号
            $msg = config("tips.account_insert_ok");
            $default_avatar = "https://fddsh.kder.top/static/default/avatar/" . rand(1, 6) . ".jpg";
            $sql = <<<sql
INSERT INTO `fd_user` ( `email`, `password`, `last_login_ip` ,`avatar`)
VALUES
	( '{$input["account"]}', '{$password}', '{$client_ip}','{$default_avatar}' )
sql;
        }
        $mysql->query($sql);

        // 退出登陆
        $this->logout();
        return $this->apiSuccess($msg);
    }

    // 校验注册输入
    public function toCheckRegisterInput($input)
    {
        // 获取验证码
        $cache = Cache::getInstance();
        $cache_code = $cache->get($input["account"]);
        // 是否合法邮箱
        if (!is_email($input["account"])) {
            $code = 0;
            $msg = config("tips.email_format_err");
        } // 验证码确认
        else if (!$cache_code || $cache_code !== $input["code"]) {
            $code = 0;
            $msg = config("tips.code_err");
        } // 密码确认
        else if ($input["password"] !== $input["re_password"]) {
            $code = 0;
            $msg = config("tips.passwd_diff_err");
        } // 输入正常
        else {
            $code = 1;
            $msg = "ok";
        }
        return compact("code", "msg");
    }

    // 校验账号密码是否正确
    // @预处理
    public function toCheckLoginInput($account, $password)
    {
        // 预处理
        $mysql = Mysql::getInstance();
        $sql = "SELECT id FROM `fd_user` WHERE (`username` = ? OR `email` = ? OR `mobile` = ?) AND `password` = ? limit 1";
        $mysql_stmt = $mysql->prepare($sql);
        $mysql_stmt->bind_param("ssss", $account, $account, $account, $password);
        $mysql_stmt->execute();
        // 绑定结果集字段（对应 field 数量）
        $mysql_stmt->bind_result($user_id);
        // 获取预处理语句结果的每条记录，并将相应的字段赋给绑定结果
        $mysql_stmt->fetch();
        $mysql_stmt->close();

        return $user_id;
    }

    /**
     * 修改登录信息（登陆时间、IP、次数等）
     * 并session保存登陆状态
     * @param $user_id
     * @return bool|\mysqli_result
     */
    public function toSetLoginInfo($user_id)
    {
        $mysql = Mysql::getInstance();
        $client_ip = get_client_ip();
        $sql = <<<sql
UPDATE `fd_user`
SET login_count = login_count + 1,
 last_login_ip = '{$client_ip}',
 update_time = NOW()
WHERE
	id = {$user_id};
sql;
        $_SESSION["isLogin"] = 1;
        return $mysql->query($sql);
    }

    /**
     * 联表获取用户信息,并保存到 $_COOKIE
     * 本意是想与前段共同操作此信息
     * 因代理问题，前段无法直接获取
     * @param $user_id
     * @return bool|mixed
     */
    public function toGetUserInfoById($user_id)
    {
        if (!(int)$user_id) {
            return false;
        }
        $mysql = Mysql::getInstance();
        $sql = <<<sql
SELECT
    u.id,username,mobile,email,avatar,motto,sex,age,`level`,vip_start_time,vip_end_time,
    (now() > vip_start_time AND now() < vip_end_time) as is_vip
FROM
	`fd_user` u
LEFT JOIN `fd_user_vip` v ON v.user_id = u.id
WHERE
	u.id = {$user_id}
sql;
        $user_info = $mysql->getFind($sql);
        // 更新用户信息
        setcookie("user_info", serialize($user_info), time() + 3600 * 24 * 7, "/");
        return $user_info;
    }

    /**
     * 检测登陆状态
     * 用于判断清空前端的localStorage
     * @return int
     */
    public function checkLoginStatus()
    {
        if (!$this->isLogin()) {
            return $this->apiError();
        }
        return $this->apiReturn($this->user);
    }

}